home *** CD-ROM | disk | FTP | other *** search
/ Shareware Overload Trio 2 / Shareware Overload Trio Volume 2 (Chestnut CD-ROM).ISO / dir27 / calctool.zip / CALCTOOL.C < prev    next >
C/C++ Source or Header  |  1994-01-11  |  19KB  |  392 lines

  1.  
  2. /*  @(#)calctool.c 1.12 89/12/07
  3.  *
  4.  *  A simple calculator program.
  5.  *
  6.  *  Copyright (c) Rich Burridge.
  7.  *                Sun Microsystems, Australia - All rights reserved.
  8.  *
  9.  *  Basic algorithms, copyright (c) Ed Falk.
  10.  *                Sun Microsystems, Mountain View.
  11.  *
  12.  *  Permission is given to distribute these sources, as long as the
  13.  *  copyright messages are not removed, and no monies are exchanged.
  14.  *
  15.  *  No responsibility is taken for any errors or inaccuracies inherent
  16.  *  either to the comments or the code of this program, but if
  17.  *  reported to me then an attempt will be made to fix them.
  18.  */
  19.  
  20. #include <stdio.h>
  21. #include <strings.h>
  22. #include <math.h>
  23. #include "patchlevel.h"
  24. #include "color.h"
  25. #include "calctool.h"
  26.  
  27. double powers[11][4] = {
  28.          {    1.0,          1.0,           1.0,             1.0 },
  29.          {    2.0,          8.0,          10.0,            16.0 },
  30.          {    4.0,         64.0,         100.0,           256.0 },
  31.          {    8.0,        512.0,        1000.0,          4096.0 },
  32.          {   16.0,       4096.0,       10000.0,         65536.0 },
  33.          {   32.0,      32768.0,      100000.0,       1048576.0 },
  34.          {   64.0,     262144.0,     1000000.0,      16777216.0 },
  35.          {  128.0,    2097152.0,    10000000.0,     268435456.0 },
  36.          {  256.0,   16777216.0,   100000000.0,    4294967296.0 },
  37.          {  512.0,  134217728.0,  1000000000.0,   68719476736.0 },
  38.          { 1024.0, 1073741824.0, 10000000000.0, 1099511627776.0 }
  39. } ;
  40.  
  41. double exp_p1[10][4] = {
  42.         { 1.0,          1.0,             1.0,    1.0             },
  43.         { 1.0,          1.0,             1.0,    1.0             },
  44.         { 0.5,          0.125,           0.1,    0.0625          },
  45.         { 0.25,         0.015625,        0.01,   3.90625e-03     },
  46.         { 0.125,        1.953125e-03,    0.001,  2.44140625e-04  },
  47.         { 0.0625,       2.44140625e-04,  1.0e-4, 1.525878906e-05 },
  48.         { 0.03125,      3.051757813e-05, 1.0e-5, 9.536743164e-07 },
  49.         { 0.015625,     3.814697266e-06, 1.0e-6, 5.960464478e-08 },
  50.         { 0.0078125,    4.768371582e-07, 1.0e-7, 3.725290298e-09 },
  51.         { 3.90625e-03,  5.960464478e-08, 1.0e-8, 2.328306437e-10 }
  52. } ;
  53.  
  54. double max_fix[4] = {
  55.           6.871947674e+10, 3.245185537e+32,
  56.           1.000000000e+36, 2.230074520e+43
  57. } ;
  58.  
  59. /* Selectable constants - these are the default selections. */
  60.  
  61. double con_vals[MAXREGS] = {
  62.          0.621,                   /* kilometres per hour <=> miles per hour. */
  63.          1.41421356237309504880,  /* square root of 2. */
  64.          2.7182818284590452354,   /* e */
  65.          3.14159265358979323846,  /* pi */
  66.          2.54,                    /* centimetres <=> inch. */
  67.          57.29577951308232,       /* degrees in a radian. */
  68.          1048576.0,               /* 2 ^ 20. */
  69.          0.0353,                  /* grams <=> ounce. */
  70.          0.948,                   /* kilojoules <=> British thermal units. */
  71.          0.0610,                  /* cubic cms <=> cubic inches. */
  72. } ;
  73.  
  74. char con_names[MAXREGS][MAXLINE] = {
  75.        "kilometres per hour <=> miles per hour.",
  76.        "square root of 2.",
  77.        "e.",
  78.        "pi.",
  79.        "centimetres <=> inch.",
  80.        "degrees in a radian.",
  81.        "2 ^ 20.",
  82.        "grams <=> ounce.",
  83.        "kilojoules <=> British thermal units.",
  84.        "cubic cms <=> cubic inches.",
  85. } ;
  86.  
  87. char num_names[MAXREGS][2] = {    /* Used by the popup menus. */
  88.        "0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
  89. } ;
  90.  
  91. char base_str[4][4]  = { "BIN", "OCT", "DEC", "HEX" } ;
  92. char dtype_str[2][4] = { "FIX", "SCI" } ;
  93. char ttype_str[3][5] = { "DEG", "GRAD", "RAD" } ;
  94.  
  95. char digits[] = "0123456789abcdef" ;
  96. int basevals[4] = {2, 8, 10, 16} ;
  97.  
  98. /* Length of display in characters for each base. */
  99. int disp_length[4] = {32, 15, 12, 12} ;
  100.  
  101. /* X offset in pixels for various length button strings. */
  102. int chxoff[5] = { 5, 9, 14, 16, 5 } ;
  103.  
  104. /* Valid keys when an error condition has occured. */
  105. /*                            MEM  KEYS HELP   clr   QUIT OFF  REDRAW */
  106. char validkeys[MAXVKEYS]  = { 'M', 'K', '?', '\177', 'q', 'o', '\f' } ;
  107.  
  108. /* Valid keys for which the right mouse button will get a popup menu. */
  109. char validmenu[MAXMENUS]  = {
  110. /*   ACC  CON    EXCH        FUN        <    >   RCL  STO  */
  111.      'A', '#', CCTRL('e'), CCTRL('f'), '<', '>', 'r', 's'
  112. } ;
  113.  
  114. double disp_val ;             /* Value of the current display. */
  115. double last_input ;           /* Previous number input by user. */
  116. double mem_vals[MAXREGS] ;    /* Memory register values. */
  117. double result ;               /* Current calculator total value. */
  118. double tresults[3] ;          /* Current trigonometric results. */
  119.  
  120. enum base_type base ;         /* Current base: BIN, OCT, DEC or HEX. */
  121. enum gr_type gtype ;          /* What graphics system is being used. */
  122. enum num_type dtype ;         /* Number display mode. */
  123. enum trig_type ttype ;        /* Trigonometric type (deg, grad or rad). */
  124.  
  125. FILE *hfd ;         /* File descriptor for help information. */
  126.  
  127. int accuracy ;      /* Number of digits precision (Max 9). */
  128. int color ;         /* Color being used for current raster operation. */
  129. int column ;        /* Column number of current key/mouse press. */
  130. int cur_ch ;        /* Current character if keyboard event. */
  131. int curx ;          /* Current mouse X position. */
  132. int cury ;          /* Current mouse Y position. */
  133. int down ;          /* Indicates is a mouse button is down. */
  134. int error ;         /* Indicates some kind of display error. */
  135. int hyperbolic ;    /* If set, trig functions will be hyperbolic. */
  136. int iconic ;        /* Set if window is currently iconic. */
  137. int inv_video ;     /* Set if user wants inverse video mode. */
  138. int inverse ;       /* If set, trig and log functions will be inversed. */
  139. int iscolor ;       /* Set if this is a color screen. */
  140. int ishelp ;        /* Set if there is a help file. */
  141. int issel ;         /* Set if valid [Get] selection. */
  142. int ix ;            /* Initial X position of the icon. */
  143. int iy ;            /* Initial Y position of the icon. */
  144. int key_exp ;       /* Set if entering exponent number. */
  145. int new_input ;     /* New number input since last op. */
  146. int nextc ;         /* Current event identifier. */
  147. int nfont_width ;   /* Width of the normal font characters. */
  148. int pending ;       /* Indicates command depending on multiple presses. */
  149. int pending_op ;    /* Arithmetic operation for pending command. */
  150. int pointed ;       /* Whether a decimal point has been given. */
  151. int portion ;       /* Portion of button on current key/mouse press. */
  152. int posspec ;       /* Set if -Wp or -g option is present (for X11) */
  153. int row ;           /* Row number of current key/mouse press. */
  154. int rstate ;        /* Indicates if memory register frame is displayed. */
  155. int spaces ;        /* Number of spaces in current button string. */
  156. int toclear ;       /* Indicates if display should be cleared. */
  157. int tstate ;        /* Indicates current button set being displayed. */
  158. int wx ;            /* Initial X position of the window. */
  159. int wy ;            /* Initial Y position of the window. */
  160. int x ;             /* X offset for text for button. */
  161. int y ;             /* Y offset for text for button. */
  162.  
  163. /* Routines obeyed by mouse button or character presses. */
  164. int close_frame(),    destroy_frame(),  do_base() ;
  165. int do_calculation(), do_clear(),       do_constant(),  do_delete() ;
  166. int do_expno(),       do_immediate(),   do_keys(),      do_number() ;
  167. int do_pending(),     do_point(),       do_portion(),   do_repaint() ;
  168. int do_set_mode(),    do_trig(),        do_trigtype(),  toggle_reg_canvas() ;
  169.  
  170. char cur_op ;                     /* Current arithmetic operation. */
  171. char current ;                    /* Current button or character pressed. */
  172. char *exp_posn ;                  /* Position of the exponent sign. */
  173. char fnum[MAX_DIGITS+1] ;         /* Scratch area for fixed point numbers. */
  174. char fun_names[MAXREGS][MAXLINE] ;  /* Function defs from .calctoolrc. */
  175. char fun_vals[MAXREGS][MAXLINE] ;   /* Function names from .calctoolrc. */
  176. char geometry[MAXLINE] ;          /* X11 geometry information. */
  177. char old_cal_value ;              /* Previous calculation operator. */
  178. char pstr[5] ;                    /* Current button text string. */
  179. char *selection ;                 /* Current [Get] selection. */
  180. char *shelf ;                     /* PUT selection shelf contents. */
  181. char snum[MAX_DIGITS+1] ;         /* Scratch are for scientific numbers. */
  182. char x11_display[MAXLINE] ;       /* X11 display information. */
  183.  
  184. struct iteminfo items[MAXITEMS] = {                    /* Panel items. */
  185.   { SFONT, BBORDER,                 DISPLAY-3,  "" },  /* BASEITEM. */
  186.   { NFONT, 0,                       DISPLAY-15, "" },  /* DISPLAYITEM. */
  187.   { SFONT, BBORDER+1*(BWIDTH+BGAP), DISPLAY-3,  "" },  /* TTYPEITEM. */
  188.   { SFONT, BBORDER+2*(BWIDTH+BGAP), DISPLAY-3,  "" },  /* NUMITEM. */
  189.   { SFONT, BBORDER+3*(BWIDTH+BGAP), DISPLAY-3,  "" },  /* HYPITEM. */
  190.   { SFONT, BBORDER+4*(BWIDTH+BGAP), DISPLAY-3,  "" },  /* INVITEM. */
  191.   { SFONT, BBORDER+5*(BWIDTH+BGAP), DISPLAY-3,  "" },  /* OPITEM. */
  192. } ;
  193.  
  194. /* Calculator button values. */
  195.  
  196. struct button buttons[TITEMS] = {
  197.   { "EXCH", CCTRL('e'), OP_SET,   MAUVE,    do_pending },       /* Row 1. */
  198.   { "CON ", '#',        OP_SET,   BLUE,     do_pending },
  199.   { "BIN ", 'B',        OP_CLEAR, YELLOW,   do_base },
  200.   { "MEM ", 'M',        OP_CLEAR, BLUE,     toggle_reg_canvas },
  201.   { "OCT ", 'O',        OP_CLEAR, YELLOW,   do_base },
  202.   { "D   ", 'd',        OP_NOP,   PINK,     do_number },
  203.   { "DEC ", 'D',        OP_CLEAR, YELLOW,   do_base },
  204.   { "E   ", 'e',        OP_NOP,   PINK,     do_number }, 
  205.   { "HEX ", 'H',        OP_CLEAR, YELLOW,   do_base },
  206.   { "F   ", 'f',        OP_NOP,   PINK,     do_number },  
  207.   { "SCI ", CCTRL('n'), OP_CLEAR, BLUE,     do_set_mode },
  208.   { "FUN ", CCTRL('f'), OP_SET,   BLUE,     do_pending },
  209.  
  210.   { "&32 ", '[',        OP_CLEAR, LGREY,    do_immediate },      /* Row 2. */
  211.   { "STO ", 's',        OP_SET,   MAUVE,    do_pending },
  212.   { "&16 ", ']',        OP_CLEAR, LGREY,    do_immediate },
  213.   { "RCL ", 'r',        OP_SET,   MAUVE,    do_pending }, 
  214.   { "<   ", '<',        OP_SET,   LGREY,    do_pending },
  215.   { "A   ", 'a',        OP_NOP,   PINK,     do_number }, 
  216.   { ">   ", '>',        OP_SET,   LGREY,    do_pending },
  217.   { "B   ", 'b',        OP_NOP,   PINK,     do_number },
  218.   { "%   ", '%',        OP_SET,   LPURPLE,  do_calculation },
  219.   { "C   ", 'c',        OP_NOP,   PINK,     do_number },
  220.   { "clr ", '\177',     OP_CLEAR, BLUE,     do_clear },
  221.   { "bsp ", CCTRL('h'), OP_NOP,   BLUE,     do_delete },
  222.  
  223.   { "OR  ", '|',        OP_SET,   GREEN,    do_calculation },   /* Row 3. */
  224.   { "AND ", '&',        OP_SET,   GREEN,    do_calculation },
  225.   { "HYP ", 'h',        OP_CLEAR, BLUE,     do_set_mode },
  226.   { "SIN ", CCTRL('s'), OP_CLEAR, LGREEN,   do_trig },
  227.   { "e^x ", '{',        OP_CLEAR, ORANGE,   do_immediate },
  228.   { "7   ", '7',        OP_NOP,   LBLUE,    do_number },
  229.   { "10^x", '}',        OP_CLEAR, ORANGE,   do_immediate },
  230.   { "8   ", '8',        OP_NOP,   LBLUE,    do_number },
  231.   { "y^x ", 'Y',        OP_SET,   ORANGE,   do_calculation },
  232.   { "9   ", '9',        OP_NOP,   LBLUE,    do_number }, 
  233.   { "INT ", 'I',        OP_CLEAR, LGREY,    do_portion },
  234.   { "X   ", 'x',        OP_SET,   LPURPLE,  do_calculation },
  235.  
  236.   { "XNOR", 'n',        OP_SET,   GREEN,    do_calculation },   /* Row 4. */
  237.   { "XOR ", '^',        OP_SET,   GREEN,    do_calculation },
  238.   { "INV ", 'i',        OP_CLEAR, BLUE,     do_set_mode },
  239.   { "COS ", CCTRL('c'), OP_CLEAR, LGREEN,   do_trig },
  240.   { "ln  ", 'N',        OP_CLEAR, ORANGE,   do_immediate },
  241.   { "4   ", '4',        OP_NOP,   LBLUE,    do_number },
  242.   { "log ", 'G',        OP_CLEAR, ORANGE,   do_immediate },
  243.   { "5   ", '5',        OP_NOP,   LBLUE,    do_number },
  244.   { "SQRT", 'S',        OP_CLEAR, ORANGE,   do_immediate },
  245.   { "6   ", '6',        OP_NOP,   LBLUE,    do_number },
  246.   { "FRAC", 'F',        OP_CLEAR, LGREY,    do_portion },
  247.   { "/   ", '/',        OP_SET,   LPURPLE,  do_calculation },
  248.  
  249.   { "NOT ", '~',        OP_CLEAR, GREEN,    do_immediate },     /* Row 5. */
  250.   { "ACC ", 'A',        OP_SET,   BLUE,     do_pending },
  251.   { "EXP ", 'E',        OP_SET,   BLUE,     do_expno },
  252.   { "TAN ", CCTRL('t'), OP_CLEAR, LGREEN,   do_trig },
  253.   { "1/x ", 'R',        OP_CLEAR, ORANGE,   do_immediate },
  254.   { "1   ", '1',        OP_NOP,   LBLUE,    do_number },
  255.   { "x!  ", '!',        OP_CLEAR, ORANGE,   do_immediate },
  256.   { "2   ", '2',        OP_NOP,   LBLUE,    do_number },
  257.   { "x^2 ", '@',        OP_CLEAR, ORANGE,   do_immediate },
  258.   { "3   ", '3',        OP_NOP,   LBLUE,    do_number },
  259.   { "CHS ", 'C',        OP_CLEAR, LGREY,    do_immediate },
  260.   { "-   ", '-',        OP_SET,   LPURPLE,  do_calculation },
  261.  
  262.   { "QUIT", 'q',        OP_CLEAR, BLUE,     destroy_frame },    /* Row 6. */
  263.   { "OFF ", 'o',        OP_CLEAR, BLUE,     close_frame },
  264.   { "KEYS", 'K',        OP_CLEAR, BLUE,     do_keys },
  265.   { "?   ", '?',        OP_SET,   BLUE,     do_pending },
  266.   { "DEG ", CCTRL('d'), OP_CLEAR, RED,      do_trigtype },
  267.   { "0   ", '0',        OP_NOP,   LBLUE,    do_number },
  268.   { "RAD ", CCTRL('r'), OP_CLEAR, RED,      do_trigtype },
  269.   { ".   ", '.',        OP_NOP,   LPURPLE,  do_point },
  270.   { "GRAD", CCTRL('g'), OP_CLEAR, RED,      do_trigtype },
  271.   { "=   ", '=',        OP_CLEAR, LPURPLE,  do_calculation },
  272.   { "ABS ", 'U',        OP_CLEAR, LGREY,    do_portion },
  273.   { "+   ", '+',        OP_SET,   LPURPLE,  do_calculation },
  274.  
  275. /* Extra definitions. */
  276.  
  277.   { "X   ", 'X',        OP_SET,   WHITE,    do_calculation },
  278.   { "X   ", '*',        OP_SET,   WHITE,    do_calculation },
  279.   { "    ", CCTRL('m'), OP_CLEAR, WHITE,    do_calculation },
  280.   { "QUIT", 'Q',        OP_CLEAR, WHITE,    destroy_frame },
  281.   { "    ", '\f',       OP_NOP,   WHITE,    do_repaint },
  282. } ;
  283.  
  284. /*  256-byte table for quickly reversing the bits in an unsigned 8-bit char,
  285.  *  used to convert between MSBFirst and LSBFirst image formats.
  286.  */
  287.  
  288. char revtable[256] = {
  289.         0, -128,   64,  -64,   32,  -96,   96,  -32,
  290.        16, -112,   80,  -48,   48,  -80,  112,  -16,
  291.         8, -120,   72,  -56,   40,  -88,  104,  -24,
  292.        24, -104,   88,  -40,   56,  -72,  120,   -8,
  293.         4, -124,   68,  -60,   36,  -92,  100,  -28,
  294.        20, -108,   84,  -44,   52,  -76,  116,  -12,
  295.        12, -116,   76,  -52,   44,  -84,  108,  -20,
  296.        28, -100,   92,  -36,   60,  -68,  124,   -4,
  297.         2, -126,   66,  -62,   34,  -94,   98,  -30,
  298.        18, -110,   82,  -46,   50,  -78,  114,  -14,
  299.        10, -118,   74,  -54,   42,  -86,  106,  -22,
  300.        26, -102,   90,  -38,   58,  -70,  122,   -6,
  301.         6, -122,   70,  -58,   38,  -90,  102,  -26,
  302.        22, -106,   86,  -42,   54,  -74,  118,  -10,
  303.        14, -114,   78,  -50,   46,  -82,  110,  -18,
  304.        30,  -98,   94,  -34,   62,  -66,  126,   -2,
  305.         1, -127,   65,  -63,   33,  -95,   97,  -31,
  306.        17, -111,   81,  -47,   49,  -79,  113,  -15,
  307.         9, -119,   73,  -55,   41,  -87,  105,  -23,
  308.        25, -103,   89,  -39,   57,  -71,  121,   -7,
  309.         5, -123,   69,  -59,   37,  -91,  101,  -27,
  310.        21, -107,   85,  -43,   53,  -75,  117,  -11,
  311.        13, -115,   77,  -51,   45,  -83,  109,  -19,
  312.        29,  -99,   93,  -35,   61,  -67,  125,   -3,
  313.         3, -125,   67,  -61,   35,  -93,   99,  -29,
  314.        19, -109,   83,  -45,   51,  -77,  115,  -13,
  315.        11, -117,   75,  -53,   43,  -85,  107,  -21,
  316.        27, -101,   91,  -37,   59,  -69,  123,   -5,
  317.         7, -121,   71,  -57,   39,  -89,  103,  -25,
  318.        23, -105,   87,  -41,   55,  -73,  119,   -9,
  319.        15, -113,   79,  -49,   47,  -81,  111,  -17,
  320.        31,  -97,   95,  -33,   63,  -65,  127,   -1,
  321. } ;
  322.  
  323. char display[MAXLINE] ;     /* Current calculator display. */
  324. char helpname[MAXLINE] ;    /* Filename for help file. */
  325. char progname[MAXLINE] ;    /* Name of this program. */
  326.  
  327.  
  328. main(argc,argv)
  329. int argc ;
  330. char *argv[] ;
  331. {
  332.   STRCPY(progname, argv[0]) ; /* Save this programs name. */
  333.   get_options(argc, argv) ;   /* Get command line arguments. */
  334.   get_helpfile(helpname) ;    /* Open helpfile if present. */
  335.   read_rcfiles() ;            /* Read .calctoolrc's files. */
  336.   if (init_ws_type())         /* Determine window system type. */
  337.     {
  338.       FPRINTF(stderr,"Error initialising window system.\n") ;
  339.       exit(1) ;
  340.     }
  341.   init_fonts() ;              /* Open required fonts. */
  342.   make_icon() ;               /* Set up the calctool window icon. */
  343.   make_frames(argc, argv) ;   /* Create calctool window frames. */
  344.   make_subframes() ;          /* Create panels and canvases. */
  345.   make_menus() ;              /* Create menus for graphics versions. */
  346.   if (gtype != X11) load_colors() ;  /* Load the initial calctool colormap. */
  347.  
  348.   shelf = NULL ;              /* No selection for shelf initially. */
  349.   pending = 0 ;               /* No initial pending command. */
  350.   rstate = 0 ;                /* No memory register frame display initially. */
  351.   tstate = 0 ;                /* Button values displayed first. */
  352.   hyperbolic = 0 ;            /* Normal trig functions initially. */
  353.   inverse = 0 ;               /* No inverse functions initially. */
  354.   base = DEC ;                /* Initial base. */
  355.   grey_buttons(base) ;
  356.   ttype = DEG ;               /* Initial trigonometric type. */
  357.   dtype = FIX ;               /* Initial number display mode. */
  358.   down = 0 ;                  /* No mouse presses initially. */
  359.  
  360.   make_items() ;              /* Create panel items and cursors. */
  361.   do_clear() ;                /* Initialise and clear display. */
  362.   set_cursor(MAINCURSOR) ;    /* Initially display the arrow cursor. */
  363.   start_tool() ;              /* Display the calculator. */
  364.   exit(0) ;
  365. }
  366.  
  367.  
  368. /* Calctools' customised math library error-handling routine. */
  369.  
  370. doerr(funcname, etype, eval)
  371. char *funcname, *etype ;
  372. int eval ;
  373. {
  374.   SPRINTF(display, "%s: %s error", funcname, etype) ;
  375.   set_item(DISPLAYITEM, display) ;
  376.   error = eval ;
  377.   set_item(OPITEM, "CLR") ;
  378. }
  379.  
  380.  
  381. /* Default math library exception handling routine. */
  382.  
  383. /*ARGSUSED*/
  384. matherr(exc)
  385. struct exception *exc ;
  386. {
  387.   STRCPY(display, "Error") ;
  388.   set_item(DISPLAYITEM, display) ;
  389.   error = 1 ;
  390.   set_item(OPITEM, "CLR") ;
  391. }
  392.